#pragma once
#include<iostream>
#include<cstdlib>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>
#include"Log.hpp"


#define PORT 8080
#define WAITLEN 3
class TcpServer{
  private:
    TcpServer(int port)
      :_port(port)
    {}
    TcpServer(const TcpServer& s)
    {}
  public:
    static TcpServer* getinstance(int port = PORT)
    {
      pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
      if(svr == nullptr)
      {
        pthread_mutex_lock(&mtx);
        if(svr == nullptr)
        {
          svr = new TcpServer(port);
          svr->InitServer();
        }
      }
      return svr;
    }
    void InitServer()
    {
      Socket();
      Bind();
      Listean();
      Log::LOG(INFO,"server is init");
    }
    int Sock()
    {
      return _listensock;
    }
    void Socket()
    {
      _listensock = socket(AF_INET,SOCK_STREAM,0);
      if(_listensock == -1)
      {
        Log::LOG(FATAL,"server create fail");
        exit(1);
      }
      int opt = 1;
      setsockopt(_listensock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
      Log::LOG(INFO,"sock is create success");
    }
    void Bind()
    {
      struct sockaddr_in local;
      local.sin_family = AF_INET;
      local.sin_port = htons(_port);
      local.sin_addr.s_addr = INADDR_ANY;
      if(bind(_listensock,(sockaddr*)&local,sizeof(local)) == -1)
      {
        Log::LOG(FATAL,"bind is fail");
        exit(2);
      }
        Log::LOG(INFO,"bind is success");
    }
    void Listean()
    {
      if(listen(_listensock,WAITLEN) == -1)
      {
        Log::LOG(FATAL,"listen is fail");
        exit(3);
      }
        Log::LOG(INFO,"listen is success");
    }
  private:
    size_t _port;
    int _listensock;
    static TcpServer* svr;
};
TcpServer* TcpServer::svr = nullptr;
